package com.cloudptt.api.product.pjsua2;

import static com.cloudptt.api.pjsip.api.SipManager.SUB_TYPE_XCAP;
import static com.cloudptt.api.pjsip.api.SipManager.SUB_TYPE_pidf;

import static org.pjsip.pjsua2.pjmedia_vid_dev_std_index.PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
import static org.pjsip.pjsua2.pjmedia_vid_dev_std_index.PJMEDIA_VID_DEFAULT_RENDER_DEV;

import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;

import com.cloudptt.api.comm.CauseCont;
import com.cloudptt.api.comm.CommInfo;
import com.cloudptt.api.models.SipMsgParser;
import com.cloudptt.api.pjsip.api.ImsProfile;
import com.cloudptt.api.pjsip.api.MessageInfo;
import com.cloudptt.api.pjsip.api.SipCallSession;
import com.cloudptt.api.pjsip.api.SipManager;
import com.cloudptt.api.product.NetWorkBroadcast;
import com.cloudptt.api.product.func.call.CallAttr;
import com.cloudptt.api.product.log.Log;
import com.mcptt.config.body.McxExtensionXml;
import com.mcptt.config.body.ResourceListsBody;
import com.mcptt.config.body.XCapBodyGms;
import com.mcptt.config.body.info.InfoBody_NewCall;
import com.mcptt.config.body.info.mcdata.binary.FdSignalBody;
import com.mcptt.config.body.info.mcdata.binary.NtfSignalBody;
import com.mcptt.config.body.info.mcdata.binary.PayloadBody;
import com.mcptt.config.body.info.mcdata.binary.SdsSignalBody;
import com.mcptt.config.body.info.mcptt.McpttInfoBody_NewCall;
import com.mcptt.config.body.info.mcvideo.McvideoInfoBody_NewCall;
import com.mcptt.db.model.AddrInfo;
import com.mcptt.db.model.SessionInfo;

import org.pjsip.pjsua2.Account;
import org.pjsip.pjsua2.AccountCallConfig;
import org.pjsip.pjsua2.AccountConfig;
import org.pjsip.pjsua2.AccountMediaConfig;
import org.pjsip.pjsua2.AccountRegConfig;
import org.pjsip.pjsua2.AuthCredInfo;
import org.pjsip.pjsua2.AuthCredInfoVector;
import org.pjsip.pjsua2.Buddy;
import org.pjsip.pjsua2.BuddyConfig;
import org.pjsip.pjsua2.CallInfo;
import org.pjsip.pjsua2.OnIncomingCallParam;
import org.pjsip.pjsua2.OnInstantMessageParam;
import org.pjsip.pjsua2.OnKeepaliveParam;
import org.pjsip.pjsua2.OnLocationParam;
import org.pjsip.pjsua2.OnMcdataFindParam;
import org.pjsip.pjsua2.OnMcdataMessageParam;
import org.pjsip.pjsua2.OnMcdataMessageStatusParam;
import org.pjsip.pjsua2.OnMwiInfoParam;
import org.pjsip.pjsua2.OnNatAddrChangeParam;
import org.pjsip.pjsua2.OnPublishParam;
import org.pjsip.pjsua2.OnRegStateParam;
import org.pjsip.pjsua2.OnResponeParam;
import org.pjsip.pjsua2.SendInstantMessageParam;
import org.pjsip.pjsua2.SendMcdataInstantMessageParam;
import org.pjsip.pjsua2.SendMcxInstantMessageParam;
import org.pjsip.pjsua2.SendTypingIndicationParam;
import org.pjsip.pjsua2.SipHeader;
import org.pjsip.pjsua2.SipHeaderVector;
import org.pjsip.pjsua2.SipMediaType;
import org.pjsip.pjsua2.SipMultipartPart;
import org.pjsip.pjsua2.StringVector;
import org.pjsip.pjsua2.pj_ice_sess_trickle;
import org.pjsip.pjsua2.pjmedia_orient;

import java.util.HashMap;
import java.util.Iterator;

public class MyAccount extends Account {
    public static String TAG = "MyAccount";
    public static String EXT_KEY = "X-Info";
    private Context ctx = null;
    private ImsProfile imsProfile = null;
    private String num = null;
    public AccountConfig accCfg;
    private AuthCredInfoVector creds = null;
    private StringVector proxies = null;
    //    private TransportConfig config = null;
//
//    private SipHeaderVector vec = null;
//    private SipHeader header = null;
    //    private MyBuddy bud = null;
    private SendTypingIndicationParam param = null;

    private MyBuddy mMcPttBuddy = null;
        private MyBuddy mMcPttFuncBuddy = null;
    private MyBuddy mMcDataBuddy = null;

    private MyBuddy mCmsMcpttBuddy = null;
    private MyBuddy mCmsMcvideoBuddy = null;
    private MyBuddy mCmsMcdataBuddy = null;
    private MyBuddy mGmsBuddy = null;
    private boolean isLogined = false;


    private HashMap<String, MyCall> callMap = new HashMap<String, MyCall>();

    MyAccount(Context ctx, ImsProfile imsProfile, String pwd) {
        super();
        Log.d(TAG, "MyAccount imsProfile = " + imsProfile + " pwd = " + pwd);
        this.ctx = ctx;
        this.imsProfile = imsProfile;
        this.num = imsProfile.getImpu();
        updateAccCfg(imsProfile,pwd);
        Log.d(TAG, "MyAccount accCfg = " + accCfg);
    }
    public void create() throws Exception {
        isLogined = false;
        this.create(accCfg);
    }

    public void modify() throws Exception
    {
        cleanBuddy();
        this.modify(accCfg); // 触发更新
    }

    public void updateAccCfg(ImsProfile imsProfile, String pwd)
    {
        Log.d(TAG, "updateAccCfg imsProfile = " + imsProfile + " pwd = " + pwd);
        this.imsProfile = imsProfile;
        this.num = imsProfile.getImpu();
        if(accCfg == null)
        {
            accCfg = new AccountConfig();
            accCfg.getPresConfig().setPublishEnabled(true);
            accCfg.getNatConfig().setIceEnabled(true);
            accCfg.getNatConfig().setIceNoRtcp(true);
            //accCfg.getNatConfig().setIceAggressiveNomination(true);
            accCfg.getNatConfig().setIceTrickle(pj_ice_sess_trickle.PJ_ICE_SESS_TRICKLE_DISABLED);
            accCfg.getNatConfig().setUdpKaIntervalSec(5);

            accCfg.getNatConfig().setContactRewriteUse(1);
            accCfg.getNatConfig().setViaRewriteUse(1);
            accCfg.getNatConfig().setUdpKaIntervalSec(30);
            accCfg.getNatConfig().setSipOutboundUse(1);

            accCfg.getNatConfig().setSipOutboundRegId("1");
            String val ="";
            String imei = CommInfo.getImei(ctx);
            Log.d(TAG, "addAccount imei = " + imei);
            if(imei != null
                    && !imei.equals(""))
            {
                val = "<urn:gsma:imei:"+imei+">";
            }
            else
            {
                String androidId = CommInfo.getAndroidId(ctx);
                val = "<urn:android:id:"+androidId+">";
            }

            Log.d(TAG, "addAccount val = " + val);
            accCfg.getNatConfig().setSipOutboundInstanceId(val);

            AccountMediaConfig mediaConfig = accCfg.getMediaConfig();
            mediaConfig.setRtcpMuxEnabled(true);
//        mediaConfig.setEnableLoopback(false);
            accCfg.setMediaConfig(mediaConfig);

            AccountCallConfig accountCallConfig = accCfg.getCallConfig();
            accountCallConfig.setPrackUse(0);
            accountCallConfig.setTimerSessExpiresSec(3600);
            accCfg.setCallConfig(accountCallConfig);

            accCfg.getVideoConfig().setAutoTransmitOutgoing(false);
            accCfg.getVideoConfig().setAutoShowIncoming(true);
            accCfg.getVideoConfig().setDefaultCaptureDevice(PJMEDIA_VID_DEFAULT_CAPTURE_DEV);
            accCfg.getVideoConfig().setDefaultRenderDevice(PJMEDIA_VID_DEFAULT_RENDER_DEV);
            accCfg.getVideoConfig().setStartKeyframeInterval(50);
            accCfg.getVideoConfig().setStartKeyframeCount(3);

            try
            {
                int cap_dev = accCfg.getVideoConfig().getDefaultCaptureDevice();
                MyApp.ep.vidDevManager().setCaptureOrient(cap_dev, pjmedia_orient.PJMEDIA_ORIENT_ROTATE_270DEG,
                        true);
//            MediaFormatVideo formatVideo = MyApp.ep.vidDevManager().getFormat(cap_dev);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
        accCfg.setIdUri(imsProfile.getImpu());

        AccountRegConfig regConfig = accCfg.getRegConfig();
        regConfig.setTimeoutSec(3600);
        String regUri = "sip:" + imsProfile.getDomain();
        Log.d(TAG, "addAccount regUri = " + regUri + " imsProfile = " + imsProfile);
        regConfig.setRegistrarUri(regUri);

        regConfig.setPsiMcptt(imsProfile.getPsiMcptt());//("sip:mcptt@192.168.1.107:5060");//
        regConfig.setPsiMcvideo(imsProfile.getPsiMcvideo());//("sip:mcvideo@192.168.1.107:5060");//
        regConfig.setPsiMcdata(imsProfile.getPsiMcdata());//("sip:mcdata@192.168.1.107:5060");//

        String pocSettingStrMcptt = imsProfile.toPocSettingBodyMcptt();
        Log.d(TAG, "addAccount pocSettingStrMcptt = " + pocSettingStrMcptt);
        regConfig.setPocMcptt(pocSettingStrMcptt);
        String pocSettingStrMcvideo = imsProfile.toPocSettingBodyMcvideo();
        Log.d(TAG, "addAccount pocSettingStrMcvideo = " + pocSettingStrMcvideo);
        regConfig.setPocMcvideo(pocSettingStrMcvideo);
        String pocSettingStrMcdata = imsProfile.toPocSettingBodyMcdata();
        Log.d(TAG, "addAccount pocSettingStrMcdata = " + pocSettingStrMcdata);
        regConfig.setPocMcdata(pocSettingStrMcdata);

        String infoBodyPublishMcptt = imsProfile.toInfoBodyPublishMcptt();
        regConfig.setBodyMcptt(infoBodyPublishMcptt);
        String infoBodyPublishMcvideo = imsProfile.toInfoBodyPublishMcvideo();
        regConfig.setBodyMcvideo(infoBodyPublishMcvideo);
        String infoBodyPublishMcdata = imsProfile.toInfoBodyPublishMcdata();
        regConfig.setBodyMcdata(infoBodyPublishMcdata);

//        accCfg.getIpChangeConfig().setReinvUseUpdate(1);


        SipHeaderVector headers = regConfig.getHeaders();

//        SipHeader authHeader = new SipHeader();           // 创建授权头
//        authHeader.setHName("X-CRSC-IP");             // 设置头名称
//        authHeader.setHValue(NetWorkBroadcast.getIpAddressString());       // 设置头值
//        headers.add(authHeader);                          // 添加到容器

        SipHeader header = new SipHeader();
        header.setHName("Accept-Contact");
        header.setHValue("*;+g.3gpp.mcptt;require;explicit, *;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcptt\";require;explicit, *;+g.3gpp.mcdata.sds;require;explicit, *;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcdata.sds\";require;explicit");
        headers.add(header);

        StringVector strVec = new StringVector();
        strVec.add(0, imsProfile.getDomain());
        accCfg.getSipConfig().setProxies(strVec);


        accCfg.getSipConfig().setContactParams(";crsc-nj;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcptt\";+g.3gpp.mcptt;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcvideo\";+g.3gpp.mcvideo;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcdata.sds\";+g.3gpp.mcdata.sds");
        creds = accCfg.getSipConfig().
                getAuthCreds();
        creds.clear();
        if (num.length() != 0) {
            creds.add(new AuthCredInfo("Digest", "*", imsProfile.getImpi(), 0,
                    pwd));
        }

        proxies = accCfg.getSipConfig().getProxies();
        proxies.clear();
        String proxy = "";
        if (proxy.length() != 0) {
            proxies.add(proxy);
        }
    }


    public void sndPublishPocSetting(int mcType,String accessToken) throws Exception {
        Log.d(TAG, "sndPublishPocSetting accessToken = " + accessToken);
        imsProfile.updateAccessToken(accessToken);

        String infoBody = imsProfile.toInfoBodyPublishMcptt();
        if(mcType == CallAttr.McType_McVideo)
        {
            infoBody = imsProfile.toInfoBodyPublishMcvideo();
        }
        else if(mcType == CallAttr.McType_McData)
        {
            infoBody = imsProfile.toInfoBodyPublishMcdata();
        }
        Log.d(TAG, "sndPublishPocSetting infoBody = " + infoBody);

        sendPublishPocSetting(mcType, imsProfile.getImpuStr(),infoBody);
    }

    public void sendPublishFuncLogx(boolean isActive, String uuId, String funcNum, boolean isForce, String initiateId) throws Exception {
        Log.d(TAG, "sendPublishFuncLogx isActive = " + isActive + " uuId = " + uuId + " funcNum = " + funcNum + " isForce = " + isForce + " initiateId = " + initiateId);
        String infoBodyStr = imsProfile.toFuncMcpttInfoBody1();
        String pidfXml = imsProfile.toFuncPidfXmlBody(uuId, funcNum, isForce, initiateId);
        Log.d(TAG, "sendPublishFuncLogx infoBodyStr = " + infoBodyStr + " pidfXml = " + pidfXml);
        sendPublishFuncLogx(isActive, imsProfile.getImpuStr(), infoBodyStr, pidfXml);
        Log.d(TAG, "sendPublishFuncLogx end");
    }

    public void sendPublishFuncLogoutAll(String[] funcNumList) throws Exception {
        Log.d(TAG, "sendPublishFuncLogxoutAll funcNumList = " + funcNumList);
        String infoBodyStr = imsProfile.toFuncMcpttInfoBody1();
        String pidfXml = imsProfile.toFuncPidfXmlBodyLogoutAll(funcNumList);
        Log.d(TAG, "sendPublishFuncLogxoutAll infoBodyStr = " + infoBodyStr + " pidfXml = " + pidfXml);
        sendPublishFuncLogx(false, imsProfile.getImpuStr(), infoBodyStr, pidfXml);
        Log.d(TAG, "sendPublishFuncLogxoutAll end");
    }

    public int subcribeCms(int mcType,String accessToken) {
        String idStr = imsProfile.getImpuStr();
        imsProfile.updateAccessToken(accessToken);

        String infoBody = null;
        if (CallAttr.McType_McPtt == mcType) {
            infoBody = imsProfile.toInfoBodyPublishMcptt();
            return subcribeCms(mCmsMcpttBuddy, idStr,infoBody,imsProfile.toSubscribeCmsGmsResourceBody(mcType));
        } else if (CallAttr.McType_McVideo == mcType) {
            infoBody = imsProfile.toInfoBodyPublishMcvideo();
            return subcribeCms(mCmsMcvideoBuddy, idStr,infoBody,imsProfile.toSubscribeCmsGmsResourceBody(mcType));
        } else if (CallAttr.McType_McData == mcType) {
            infoBody = imsProfile.toInfoBodyPublishMcdata();
            return subcribeCms(mCmsMcdataBuddy, idStr,infoBody,imsProfile.toSubscribeCmsGmsResourceBody(mcType));
        }
        return CauseCont.OperateErr_Exception;
    }

    private int subcribeCms(Buddy buddy, String idStr,String infoStr,String xcapStr) {
        Log.d(TAG, "subcribeCms xcapStr = " + xcapStr);
        try {
            if (buddy != null) {
                buddy.subscribeCmsGms(true, idStr,infoStr,xcapStr);
            }
        } catch (Exception e) {
            Log.d(TAG, "subcribeCms e2 = " + e);
            e.printStackTrace();
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int subcribeGms(String[] groupIdArray,String accessToken) {
        Log.d(TAG, "subcribeGms groupIdArray = " + groupIdArray);

//        String infoBodyStr = imsProfile.toFuncMcpttInfoBody1();
        try {
            imsProfile.updateAccessToken(accessToken);
            String idStr = imsProfile.getImpuStr();
            String infoBody = imsProfile.toInfoBodyPublishMcptt();

            XCapBodyGms body = new XCapBodyGms(groupIdArray);
            String str = body.toString();
            Log.d(TAG, "subcribeGms str = " + str);
            if (mGmsBuddy != null) {
                mGmsBuddy.subscribeCmsGms(true, idStr,infoBody,str);
            }
        } catch (Exception e) {
            Log.d(TAG, "subcribeGms e2 = " + e);
            e.printStackTrace();
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int subcribeFuncSelf() {
        Log.d(TAG, "subcribeFuncSelf");
        try {
            if (mMcPttBuddy != null) {
                String idStr = imsProfile.getImpuStr();
                Log.d(TAG, "subcribeFuncSelf idStr = " + idStr);
                String infoBodyStr = imsProfile.toFuncMcpttInfoBody1();
                Log.d(TAG, "subcribeFuncSelf infoBodyStr = " + infoBodyStr);

                mMcPttBuddy.subscribeFunc(true, idStr,infoBodyStr,"");
            }
        } catch (Exception e) {
            Log.d(TAG, "subcribeFuncSelf e2 = " + e);
            e.printStackTrace();
        }
        return CauseCont.OperateCheck_Suc;
    }
    public int subcribeFunc(String uuId, String funcNum) {
        Log.d(TAG, "subcribeFunc uuId = " + uuId);
        try {
            if (mMcPttBuddy != null) {
                String idStr = imsProfile.getImpuStr();
                Log.d(TAG, "subcribeFunc idStr = " + idStr);
                String infoBodyStr = imsProfile.toFuncMcpttInfoBody1();
                Log.d(TAG, "subcribeFunc infoBodyStr = " + infoBodyStr);
                String pidfXml = "";
                pidfXml = imsProfile.toFuncPidfXmlBody(uuId, funcNum, false, "");
                Log.d(TAG, "subcribeFunc pidfXml = " + pidfXml);
                mMcPttBuddy.subscribeFunc(false, idStr,infoBodyStr,pidfXml);
            }
        } catch (Exception e) {
            Log.d(TAG, "subcribeFunc e2 = " + e);
            e.printStackTrace();
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int sendCmdMessage(String peerMcpttId,String cmdType)
    {
        if (mMcPttBuddy == null) {
            return CauseCont.OperateErr_Exception;
        }
        SendMcxInstantMessageParam prm = new SendMcxInstantMessageParam();
        try {
            SipHeaderVector vec = new SipHeaderVector();
            SipHeader contactHeader1 = getSipHeader("Accept-Contact", "*;+g.3gpp.mcptt;require;explicit");
            vec.add(contactHeader1);

            SipHeader contactHeader2 = getSipHeader("Accept-Contact", "*;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcptt\";require;explicit");
            vec.add(contactHeader2);

            SipHeader idHeader = getSipHeader("P-Preferred-Identity", "<" + imsProfile.getImpu() + ">");
            vec.add(idHeader);

            SipHeader serviceHeader = getSipHeader("P-Preferred-Service", "urn:urn-7:3gpp-service.ims.icsi.mcptt");
            vec.add(serviceHeader);

            prm.getTxOption().setHeaders(vec);

            String infoStr = imsProfile.toLocationMcpttInfoRequestCallBody(cmdType);
            Log.debug(this.getClass(), "sendCmdMessage infoStr = " + infoStr);
            SipMultipartPart infoPart = MyBuddy.getSipMultipartPart("application", "vnd.3gpp.mcptt-info+xml", infoStr);
            prm.getTxOption().getMultipartParts().add(infoPart);

            ResourceListsBody resourceListsBody = new ResourceListsBody(peerMcpttId);
            Log.debug(this.getClass(), "sendSdsMessage resourceListsBody = " + resourceListsBody);
            SipMultipartPart localPart = MyBuddy.getSipMultipartPart("application", "resource-lists+xml", resourceListsBody.toString());
            prm.getTxOption().getMultipartParts().add(localPart);

            SipMediaType mulType = new SipMediaType();
            mulType.setType("multipart");
            mulType.setSubType("mixed");
            prm.getTxOption().setMultipartContentType(mulType);

//            prm.getTxOption().setContentType("application/mcx-extension+xml");
//            McxExtensionXml xml = new McxExtensionXml(imsProfile.getClientId(),type);
//            prm.getTxOption().setMsgBody(xml.toString());
//
            mMcPttBuddy.sendMcxInstantMessage(prm);
        } catch (Exception e) {
            Log.d(TAG, "sendLocationMessage e2 = " + e);
            e.printStackTrace();
            return CauseCont.OperateErr_Exception;
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int sendSysMessage(String type)
    {
        if (mMcPttBuddy == null) {
            return CauseCont.OperateErr_Exception;
        }
        SendMcxInstantMessageParam prm = new SendMcxInstantMessageParam();
        try {
            SipHeaderVector vec = new SipHeaderVector();
            SipHeader contactHeader1 = getSipHeader("Accept-Contact", "*;+g.3gpp.mcptt;require;explicit");
            vec.add(contactHeader1);

            SipHeader contactHeader2 = getSipHeader("Accept-Contact", "*;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcptt\";require;explicit");
            vec.add(contactHeader2);

            SipHeader idHeader = getSipHeader("P-Preferred-Identity", "<" + imsProfile.getImpu() + ">");
            vec.add(idHeader);

            SipHeader serviceHeader = getSipHeader("P-Preferred-Service", "urn:urn-7:3gpp-service.ims.icsi.mcptt");
            vec.add(serviceHeader);

            prm.getTxOption().setHeaders(vec);

            prm.getTxOption().setContentType("application/mcx-extension+xml");
            McxExtensionXml xml = new McxExtensionXml(imsProfile.getClientId(),type);
            prm.getTxOption().setMsgBody(xml.toString());

            mMcPttBuddy.sendMcxInstantMessage(prm);
        } catch (Exception e) {
            Log.d(TAG, "sendLocationMessage e2 = " + e);
            e.printStackTrace();
            return CauseCont.OperateErr_Exception;
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int sendLocationMessage(String locationInfoStr) {
//        Log.debug(this.getClass(), "sendLocationMessage locationInfoStr = " + locationInfoStr);
        if (mMcPttBuddy == null) {
            return CauseCont.OperateErr_Exception;
        }
        SendMcxInstantMessageParam prm = new SendMcxInstantMessageParam();
        try {
            SipHeaderVector vec = new SipHeaderVector();
            SipHeader contactHeader1 = getSipHeader("Accept-Contact", "*;+g.3gpp.mcptt;require;explicit");
            vec.add(contactHeader1);

            SipHeader contactHeader2 = getSipHeader("Accept-Contact", "*;+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mcptt\";require;explicit");
            vec.add(contactHeader2);

            SipHeader idHeader = getSipHeader("P-Preferred-Identity", "<" + imsProfile.getImpu() + ">");
            vec.add(idHeader);

            SipHeader serviceHeader = getSipHeader("P-Preferred-Service", "urn:urn-7:3gpp-service.ims.icsi.mcptt");
            vec.add(serviceHeader);

            prm.getTxOption().setHeaders(vec);

            String infoStr = imsProfile.toLocationMcpttInfoBody();
            Log.debug(this.getClass(), "sendLocationMessage infoStr = " + infoStr);
            SipMultipartPart infoPart = MyBuddy.getSipMultipartPart("application", "vnd.3gpp.mcptt-info+xml", infoStr);
            prm.getTxOption().getMultipartParts().add(infoPart);

            SipMultipartPart localPart = MyBuddy.getSipMultipartPart("application", "vnd.3gpp.mcptt-location-info+xml", locationInfoStr);
            prm.getTxOption().getMultipartParts().add(localPart);

            SipMediaType mulType = new SipMediaType();
            mulType.setType("multipart");
            mulType.setSubType("mixed");
            prm.getTxOption().setMultipartContentType(mulType);

            mMcPttBuddy.sendMcxInstantMessage(prm);
        } catch (Exception e) {
            Log.d(TAG, "sendLocationMessage e2 = " + e);
            e.printStackTrace();
            return CauseCont.OperateErr_Exception;
        }
        return CauseCont.OperateCheck_Suc;
    }

    private SipHeader getSipHeader(String name, String value) {
        SipHeader header = new SipHeader();
        header.setHName(name);
        header.setHValue(value);
        return header;
    }


    public int sendFdFindMessage() {
        Log.debug(this.getClass(), "sendFdFindMessage");
        if (mMcDataBuddy == null) {
            return CauseCont.OperateErr_Exception;
        }
        SendInstantMessageParam prm = new SendInstantMessageParam();
        try {
            String msgType = SessionInfo.MsgType_Desc_Msf_Disc_Req;
            String sendMcdataId = imsProfile.getMcdataId();
            SipHeaderVector ves = mMcDataBuddy.getMsgDataSipHeaderVector(msgType, sendMcdataId);
            prm.getTxOption().setHeaders(ves);

            prm.setContentType("application/vnd.3gpp.mcdata-info+xml");
            String infoStr = imsProfile.toFdFindMcdataInfoBody(msgType);
            prm.setContent(infoStr);
            mMcDataBuddy.sendInstantMessage(prm);
        } catch (Exception e) {
            Log.d(TAG, "sendMessage e2 = " + e);
            e.printStackTrace();
            return CauseCont.OperateErr_Exception;
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int sendSdsMessage(int type,final MessageInfo msgInfo, final String peerNumber) {
        Log.d(TAG, "sendSdsMessage type = " + type + " msgInfo = " + msgInfo + " peerNumber = " + peerNumber);
        String peerMcdataId = AddrInfo.toUrlFromNum(peerNumber);
        if (mMcDataBuddy == null) {
            return CauseCont.OperateErr_Exception;
        }
        SendMcdataInstantMessageParam prm = new SendMcdataInstantMessageParam();
        try {
            String msgType = msgInfo.getMsgType();
            String sendMcdataId = imsProfile.getMcdataId();
            SipHeaderVector ves = mMcDataBuddy.getMsgDataSipHeaderVector(msgType, sendMcdataId);
            prm.getTxOption().setHeaders(ves);
            if (SessionInfo.isOtoMsg(msgType)) {
                ResourceListsBody resourceListsBody = new ResourceListsBody(peerMcdataId);
                Log.debug(this.getClass(), "sendSdsMessage resourceListsBody = " + resourceListsBody);
                prm.setResourceList(resourceListsBody.toString());
            }

//            int type = SessionInfo.Type_Normal;
//            if(AddrInfo.isFuncNum(peerNumber))
//            {
//                type = SessionInfo.Type_Func;
//            }
//            String infoStr = imsProfile.toMcdataInfoBody(type, msgType, peerMcdataId);
//            if (SessionInfo.Type_Func == type) {
            String funcUrl = msgInfo.getSenderFuncUrl();
            String infoStr = imsProfile.toFuncMcdataInfoBody(type, msgType, peerMcdataId, funcUrl);
//            }
            prm.setInfoStr(infoStr);

            String signallingStr = SdsSignalBody.toBodyStr(msgInfo);
            Log.debug(this.getClass(), "sendSdsMessage signallingStr = " + signallingStr);
            prm.setSignallingStr(signallingStr);

            String content = msgInfo.getContent();
            String payloadStr = PayloadBody.toSdsBodyStr(content);
            Log.debug(this.getClass(), "sendSdsMessage payloadStr = " + payloadStr);
            prm.setPayloadStr(payloadStr);

            String msgId = msgInfo.getIdStr();
            Log.debug(this.getClass(), "sendSdsMessage msgId = " + msgId);
            prm.setIdStr(msgId);

            mMcDataBuddy.sendMcdataInstantMessage(prm);
        } catch (Exception e) {
            Log.d(TAG, "sendMessage e2 = " + e);
            e.printStackTrace();
            return CauseCont.OperateErr_Exception;
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int sendFdMessage(int type,final MessageInfo msgInfo, final String peerNumber) {
        Log.d(TAG, "sendFdMessage type = " + type + " msgInfo = " + msgInfo + " peerNumber = " + peerNumber);
        String peerMcdataId = AddrInfo.toUrlFromNum(peerNumber);
        if (mMcDataBuddy == null) {
            return CauseCont.OperateErr_Exception;
        }
        SendMcdataInstantMessageParam prm = new SendMcdataInstantMessageParam();
        try {
            String msgType = msgInfo.getMsgType();
            String sendMcdataId = imsProfile.getMcdataId();
            SipHeaderVector ves = mMcDataBuddy.getMsgDataSipHeaderVector(msgType, sendMcdataId);
            prm.getTxOption().setHeaders(ves);
            if (SessionInfo.isOtoMsg(msgType)) {
                ResourceListsBody resourceListsBody = new ResourceListsBody(peerMcdataId);
                Log.debug(this.getClass(), "sendFdMessage resourceListsBody = " + resourceListsBody);
                prm.setResourceList(resourceListsBody.toString());
            }
//            int type = msgInfo.getType();
//            int type = SessionInfo.Type_Normal;
//            if(AddrInfo.isFuncNum(peerNumber))
//            {
//                type = SessionInfo.Type_Func;
//            }
            Log.debug(this.getClass(), "sendFdMessage type = " + type);
            String infoStr = imsProfile.toMcdataInfoBody(type, msgType, peerMcdataId);
//            if (SessionInfo.Type_Func == type) {
            String funcUrl = msgInfo.getSenderFuncUrl();
            infoStr = imsProfile.toFuncMcdataInfoBody(type, msgType, peerMcdataId, funcUrl);
//            }
            prm.setInfoStr(infoStr);

            String signallingStr = FdSignalBody.toBodyStr(msgInfo);
            Log.debug(this.getClass(), "sendFdMessage signallingStr = " + signallingStr);
            prm.setSignallingStr(signallingStr);
            String idStr = msgInfo.getIdStr();
            Log.debug(this.getClass(), "sendFdMessage idStr = " + idStr);
            prm.setIdStr(idStr);

            mMcDataBuddy.sendMcdataInstantMessage(prm);
        } catch (Exception e) {
            Log.d(TAG, "sendMessage e2 = " + e);
            e.printStackTrace();
            return CauseCont.OperateErr_Exception;
        }
        return CauseCont.OperateCheck_Suc;
    }

    public int sendNtfMessage(final MessageInfo msgInfo, final String peerNumber) {
        Log.d(TAG, "sendNtfMessage msgInfo = " + msgInfo + " peerNumber = " + peerNumber);
        String peerMcdataId = AddrInfo.toUrlFromNum(peerNumber);
        if (mMcDataBuddy == null) {
            return CauseCont.OperateErr_Exception;
        }
        SendMcdataInstantMessageParam prm = new SendMcdataInstantMessageParam();
        try {
            String msgType = msgInfo.getMsgType();
            String sendMcdataId = imsProfile.getMcdataId();
            SipHeaderVector ves = mMcDataBuddy.getMsgDataSipHeaderVector(msgType, sendMcdataId);
            prm.getTxOption().setHeaders(ves);
            Log.debug(this.getClass(), "sendNtfMessage msgType = " + msgType);

            String id = msgInfo.getSenderFuncUrl();
            Log.debug(this.getClass(), "sendNtfMessage id = " + id);
            String dstUrl = AddrInfo.toUrlFromNum(id);
            Log.debug(this.getClass(), "sendNtfMessage dstUrl = " + dstUrl);
            ResourceListsBody resourceListsBody = new ResourceListsBody(dstUrl);
            Log.debug(this.getClass(), "sendNtfMessage resourceListsBody = " + resourceListsBody);
            prm.setResourceList(resourceListsBody.toString());

            String controllerPsi = msgInfo.getControllerPsi();
            String groupId = "";
            if (!SessionInfo.isOtoMsg(msgType)) {
                groupId = AddrInfo.toUrlFromNum(peerNumber);
            }
            String infoStr = imsProfile.toMcdataNotifyInfoBody(controllerPsi,groupId);
            prm.setInfoStr(infoStr);

            boolean isFd = SessionInfo.isFdMsg(msgType);
            String signallingStr = NtfSignalBody.toBodyStr(isFd, msgInfo);
            Log.debug(this.getClass(), "sendNtfMessage signallingStr = " + signallingStr);
            prm.setSignallingStr(signallingStr);
            String idStr = msgInfo.getNotifyIdStr();
            Log.debug(this.getClass(), "sendNtfMessage idStr = " + idStr);
            prm.setIdStr(idStr);

            mMcDataBuddy.sendMcdataInstantMessage(prm);
        } catch (Exception e) {
            Log.d(TAG, "sendMessage e2 = " + e);
            e.printStackTrace();
            return CauseCont.OperateErr_Exception;
        }
        return CauseCont.OperateCheck_Suc;
    }


    @Override
    public void onRegState(OnRegStateParam prm) {
        Log.d(TAG, "onRegState prm : code = " + prm.getCode() + "; exp = " + prm.getExpiration());
        long expiration = prm.getExpiration();

        int code = prm.getCode();
        String msgName = SipManager.ACTION_SIP_REG;
        if (expiration == 0) {
            msgName = SipManager.ACTION_SIP_UNREG;
        }
        if (code == 503) {//status=503 (Transport not available for use (PJSIP_ETPNOTAVAIL))
            return;
        }

        Log.d(TAG, "onRegState code = " + code + " num = " + num + " expiration = " + expiration + " msgName = " + msgName);
        Intent intent = new Intent(msgName);
        intent.putExtra(SipManager.RESULT_CODE, code);
        intent.putExtra(SipManager.RESULT_NUM, num);

        if (code / 100 == 2
            && expiration != 0 ) {
            String mcId = AddrInfo.toNumFromSipUrl(num);
            String defaultName = AddrInfo.getDefaultName(mcId);
            Log.d(TAG, "onRegState defaultName = " + defaultName);
            intent.putExtra(SipManager.RESULT_NAME, defaultName);
            Log.d(TAG, "onRegState isLogined = " + isLogined);
            if(!isLogined) {
                initMcPttBuddy();
                initMcDataBuddy();

                initCmsMcpttBuddy();
                initCmsMcvideoBuddy();
                initCmsMcdataBuddy();
                initGmsBuddy();

                isLogined = true;
            }
        } else {
            intent.putExtra(SipManager.RESULT_NAME, "");
        }

        ctx.sendBroadcast(intent, SipManager.PERMISSION_USE_SIP);
    }

    @Override
    public void onKeepAlive(OnKeepaliveParam prm) {
        super.onKeepAlive(prm);
        if(prm != null
                && prm.getCount() >= 3)
        {
            Log.d(TAG, "onKeepAlive prm.getCount() = " + prm.getCount());
            Intent intent = new Intent(SipManager.ACTION_NAT_KEEPALIVE_ERR);
            ctx.sendBroadcast(intent, SipManager.PERMISSION_USE_SIP);
        }
    }

    @Override
    public void onNatAddrChange(OnNatAddrChangeParam prm) {
        super.onNatAddrChange(prm);
        Log.d(TAG, "onNatAddrChange" );
        try {
//            this.setRegistration(true);
            Intent intent = new Intent(SipManager.ACTION_NAT_ADDR_CHANGE);
            ctx.sendBroadcast(intent, SipManager.PERMISSION_USE_SIP);
        }catch (Exception e)
        {
            e.printStackTrace();
            Log.d(TAG, "onNatAddrChange e = " + e );
        }
    }

    private void initMcPttBuddy() {
        BuddyConfig cfg = new BuddyConfig();
        String sipUrl = imsProfile.getPsiMcptt();
        Log.d(TAG, "initMcPttBuddy sipUrl = " + sipUrl);
        cfg.setUri(sipUrl);
        cfg.setAccId(this.getId());
        cfg.setMcType(CallAttr.McType_McPtt);
        cfg.setSubscribe(false);
//        cfg.setIdStr(imsProfile.getImpuStr());
//        String infoBodyStr = imsProfile.toFuncMcpttInfoBody1();
//        Log.d(TAG, "subcribe infoBodyStr = " + infoBodyStr);
//        cfg.setInfoStr(infoBodyStr);
        mMcPttBuddy = new MyBuddy(cfg);
        try {
            mMcPttBuddy.create(this, cfg);
        } catch (Exception e) {
            Log.d(TAG, "initMcdataBuddy e1 = " + e);
            mMcPttBuddy.delete();
            mMcPttBuddy = null;
        }
    }

    private void initMcDataBuddy() {
        BuddyConfig cfg = new BuddyConfig();
        String sipUrl = imsProfile.getPsiMcdata();
        Log.d(TAG, "initMcDataBuddy sipUrl = " + sipUrl);
        cfg.setUri(sipUrl);
        cfg.setAccId(this.getId());
        cfg.setMcType(CallAttr.McType_McData);
        cfg.setSubscribe(false);
        mMcDataBuddy = new MyBuddy(cfg);
        try {
            mMcDataBuddy.create(this, cfg);
        } catch (Exception e) {
            Log.d(TAG, "initMcdataBuddy e1 = " + e);
            mMcDataBuddy.delete();
            mMcDataBuddy = null;
        }
    }

    private void initCmsMcpttBuddy() {
        BuddyConfig cfg = new BuddyConfig();
        String sipUrl = imsProfile.getPsiCms();
        Log.d(TAG, "initCmsMcpttBuddy sipUrl = " + sipUrl);
        cfg.setUri(sipUrl);
        cfg.setAccId(this.getId());
        cfg.setMcType(CallAttr.McType_McPtt);
        cfg.setSubscribe(false);
        mCmsMcpttBuddy = new MyBuddy(cfg);
        try {
            mCmsMcpttBuddy.create(this, cfg);
        } catch (Exception e) {
            Log.d(TAG, "initCmsBuddy e1 = " + e);
            mCmsMcpttBuddy.delete();
            mCmsMcpttBuddy = null;
        }
    }
    private void initCmsMcvideoBuddy() {
        BuddyConfig cfg = new BuddyConfig();
        String sipUrl = imsProfile.getPsiCms();
        Log.d(TAG, "initCmsBuddy sipUrl = " + sipUrl);
        cfg.setUri(sipUrl);
        cfg.setAccId(this.getId());
        cfg.setMcType(CallAttr.McType_McVideo);
        cfg.setSubscribe(false);
        mCmsMcvideoBuddy = new MyBuddy(cfg);
        try {
            mCmsMcvideoBuddy.create(this, cfg);
        } catch (Exception e) {
            Log.d(TAG, "initCmsBuddy e1 = " + e);
            mCmsMcvideoBuddy.delete();
            mCmsMcvideoBuddy = null;
        }
    }
    private void initCmsMcdataBuddy() {
        BuddyConfig cfg = new BuddyConfig();
        String sipUrl = imsProfile.getPsiCms();
        Log.d(TAG, "initCmsBuddy sipUrl = " + sipUrl);
        cfg.setUri(sipUrl);
        cfg.setAccId(this.getId());
        cfg.setMcType(CallAttr.McType_McData);
        cfg.setSubscribe(false);
        mCmsMcdataBuddy = new MyBuddy(cfg);
        try {
            mCmsMcdataBuddy.create(this, cfg);
        } catch (Exception e) {
            Log.d(TAG, "initCmsBuddy e1 = " + e);
            mCmsMcdataBuddy.delete();
            mCmsMcdataBuddy = null;
        }
    }

    private void initGmsBuddy() {
        BuddyConfig cfg = new BuddyConfig();
        String sipUrl = imsProfile.getPsiGms();
        Log.d(TAG, "initGmsBuddy sipUrl = " + sipUrl);
        cfg.setUri(sipUrl);
        cfg.setAccId(this.getId());
        cfg.setMcType(CallAttr.McType_McPtt);
        cfg.setSubscribe(false);
        mGmsBuddy = new MyBuddy(cfg);
        try {
            mGmsBuddy.create(this, cfg);
        } catch (Exception e) {
            Log.d(TAG, "initGmsBuddy e1 = " + e);
            mGmsBuddy.delete();
            mGmsBuddy = null;
        }
    }

    @Override
    public void onIncomingCall(OnIncomingCallParam prm) {
        Log.d(TAG, "onIncomingCall prm = " + prm);
        MyCall call = new MyCall(ctx, this, prm.getCallId());
        InfoBody_NewCall newCallInfo = null;
        int priority = 0;
        CallInfo info = null;
        boolean hasVideo = false;
        try {
            info = call.getInfo();
            String allMsgStr = prm.getRdata().getWholeMsg();
            Log.d(TAG, "onIncomingCall allMsgStr = " + allMsgStr);
            SipMsgParser parser = new SipMsgParser(allMsgStr);
            priority = parser.getPriorityValue();
            Log.d(TAG, "onIncomingCall priority = " + priority);

            String infoBody = prm.getRdata().getInfoBody("vnd.3gpp.mcptt-info+xml");
            Log.d(TAG, "onIncomingCall infoBody = " + infoBody);
            if (infoBody != null
                    && !infoBody.trim().equals("")) {
                newCallInfo = McpttInfoBody_NewCall.parseXmlStr(infoBody);
            } else {
                infoBody = prm.getRdata().getInfoBody("vnd.3gpp.mcvideo-info+xml");
                Log.d(TAG, "onIncomingCall video infoBody = " + infoBody);
                if (infoBody != null
                        && !infoBody.trim().equals("")) {
                    hasVideo = true;
                    newCallInfo = McvideoInfoBody_NewCall.parseXmlStr(infoBody);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        Log.d(TAG, "onIncomingCall newCallInfo = " + newCallInfo + " info = " + info);
        if (newCallInfo != null
                && info != null) {

            int callType = newCallInfo.getCallType();
            Log.d(TAG, "onIncomingCall callType = " + callType);
            String callKey = info.getCallIdString();
            call.updateCallInfo(callKey, callType, CallAttr.CallDir_MT);

            Log.d(TAG, "onIncomingCall newCallInfo = " + newCallInfo);
            SipCallSession session = SipCallSession.toSipCallSession(info, newCallInfo.getCallType(), newCallInfo.hasVideo(), newCallInfo.isEmergency(), newCallInfo.getCalling(),priority);

            session.setIncoming(true);
            session.setHasVideo(hasVideo);
            Log.d(TAG, "onIncomingCall callType = " + callType + " info.getRemVideoCount() = " + info.getRemVideoCount());

            if (info.getRemVideoCount() > 0) {
                hasVideo = true;
            }
            session.setHasVideo(hasVideo);
            call.setSession(session);
            this.addMyCall(info.getCallIdString(), call);
            Log.d(TAG, "onIncomingCall 2 callType = " + callType);
            if (CallAttr.isGroupCall(callType)) {
                Intent intent = new Intent(SipManager.ACTION_SIP_CALL_INCOMING);
                intent.putExtra(SipManager.EXTRA_CALL_INFO, session);
//                intent.putExtra(SipManager.EXTRA_CALL_PRIORITY, priority);
                ctx.sendBroadcast(intent, SipManager.PERMISSION_USE_SIP);
            } else {
                Intent intent = new Intent(SipManager.ACTION_SINGLE_CALL_INCOMING);
                intent.putExtra(SipManager.EXTRA_CALL_INFO, session);
//                intent.putExtra(SipManager.EXTRA_CALL_PRIORITY, priority);
                ctx.sendBroadcast(intent, SipManager.PERMISSION_USE_SIP);
            }
        }
    }

    public void clean() {
        Log.debug(this.getClass(),"clean");
        isLogined = false;
        if (callMap != null
                && callMap.size() > 0) {
            for (Iterator<String> itor = callMap.keySet().iterator(); itor.hasNext(); ) {
                String key = itor.next();
                if (callMap.get(key) != null) {
                    MyCall call = callMap.get(key);
                    if (call != null) {
                        call.clean();
                        call.delete();
                        call = null;
                    }
                    itor.remove();
                }
            }
        }
        Log.debug(this.getClass(),"clean call ");
        try {
            String idStr = imsProfile.getImpuStr();
            String infoBodyStr = imsProfile.toFuncMcpttInfoBody1();
            if (mCmsMcpttBuddy != null) {
                mCmsMcpttBuddy.subscribeCmsGms(false,idStr,"","");
                mCmsMcpttBuddy.delete();
                mCmsMcpttBuddy = null;
            }
            Log.debug(this.getClass(),"clean mCmsMcpttBuddy ");
            if (mCmsMcvideoBuddy != null) {
                mCmsMcvideoBuddy.subscribeCmsGms(false,idStr,"","");
                mCmsMcvideoBuddy.delete();
                mCmsMcvideoBuddy = null;
            }
            Log.debug(this.getClass(),"clean mCmsMcvideoBuddy ");
            if (mCmsMcdataBuddy != null) {
                mCmsMcdataBuddy.subscribeCmsGms(false,idStr,"","");
                mCmsMcdataBuddy.delete();
                mCmsMcdataBuddy = null;
            }
            Log.debug(this.getClass(),"clean mGmsBuddy ");
            if (mGmsBuddy != null) {
                mGmsBuddy.subscribeCmsGms(false,idStr,"","");
                mGmsBuddy.delete();
                mGmsBuddy = null;
            }
//            if(mMcPttFuncBuddy != null)
//            {
//                mMcPttFuncBuddy.delete();
//                mMcPttFuncBuddy =null;
//            }
            Log.debug(this.getClass(),"clean mMcPttBuddy ");
            if (mMcPttBuddy != null) {
                mMcPttBuddy.subscribeFunc(false, idStr,"","");
                mMcPttBuddy.delete();
                mMcPttBuddy = null;
            }
//            Log.debug(this.getClass(),"clean mMcVideoBuddy ");
//            if (mMcVideoBuddy != null) {
//                mMcVideoBuddy.delete();
//                mMcVideoBuddy = null;
//            }
            Log.debug(this.getClass(),"clean mMcDataBuddy ");
            if (mMcDataBuddy != null) {
                mMcDataBuddy.delete();
                mMcDataBuddy = null;
            }
            Log.debug(this.getClass(),"clean all ");
            SystemClock.sleep(2000);
        }
        catch (Exception e)
        {
            Log.debug(this.getClass(),"clean e = " + e);
        }

        this.delete();
    }

    public void cleanBuddy()
    {
        Log.debug(this.getClass(),"cleanBuddy");
        isLogined = false;
        if (callMap != null
                && callMap.size() > 0) {
            for (Iterator<String> itor = callMap.keySet().iterator(); itor.hasNext(); ) {
                String key = itor.next();
                if (callMap.get(key) != null) {
                    MyCall call = callMap.get(key);
                    if (call != null) {
                        call.clean();
                        call.delete();
                        call = null;
                    }
                    itor.remove();
                }
            }
        }
        Log.debug(this.getClass(),"cleanBuddy call ");
        try {
            if (mCmsMcpttBuddy != null) {
//                mCmsMcpttBuddy.subscribeCmsGms(false,idStr,"");
                mCmsMcpttBuddy.delete();
                mCmsMcpttBuddy = null;
            }
            Log.debug(this.getClass(),"cleanBuddy mCmsMcpttBuddy ");
            if (mCmsMcvideoBuddy != null) {
//                mCmsMcvideoBuddy.subscribeCmsGms(false,idStr,"");
                mCmsMcvideoBuddy.delete();
                mCmsMcvideoBuddy = null;
            }
            Log.debug(this.getClass(),"cleanBuddy mCmsMcvideoBuddy ");
            if (mCmsMcdataBuddy != null) {
//                mCmsMcdataBuddy.subscribeCmsGms(false,idStr,"");
                mCmsMcdataBuddy.delete();
                mCmsMcdataBuddy = null;
            }
            Log.debug(this.getClass(),"cleanBuddy mGmsBuddy ");
            if (mGmsBuddy != null) {
//                mGmsBuddy.subscribeCmsGms(false,idStr,"");
                mGmsBuddy.delete();
                mGmsBuddy = null;
            }
//            if(mMcPttFuncBuddy != null)
//            {
//                mMcPttFuncBuddy.delete();
//                mMcPttFuncBuddy =null;
//            }
            Log.debug(this.getClass(),"cleanBuddy mMcPttBuddy ");
            if (mMcPttBuddy != null) {
//                mMcPttBuddy.subscribeFunc(false, idStr,"","");
                mMcPttBuddy.delete();
                mMcPttBuddy = null;
            }
//            Log.debug(this.getClass(),"clean mMcVideoBuddy ");
//            if (mMcVideoBuddy != null) {
//                mMcVideoBuddy.delete();
//                mMcVideoBuddy = null;
//            }
            Log.debug(this.getClass(),"cleanBuddy mMcDataBuddy ");
            if (mMcDataBuddy != null) {
                mMcDataBuddy.delete();
                mMcDataBuddy = null;
            }
        }
        catch (Exception e)
        {
            Log.debug(this.getClass(),"clean e = " + e);
        }
    }


    @Override
    public void onInstantMessage(OnInstantMessageParam prm) {
        Log.d(TAG, "onInstantMessage prm = " + prm);
        String body = prm.getMsgBody();
        Log.d(TAG, "onInstantMessage body = " + body);

        String exXml = prm.getRdata().getInfoBody(SipManager.SUB_TYPE_EXTENSION);
        Log.d(TAG, "onInstantMessage exXml = " + exXml);
        if (exXml != null
                && !exXml.equals("")) {

            Intent intent = new Intent(SipManager.ACTION_SIP_MESSAGE_SYS);
            intent.putExtra(SipManager.Body_Str, exXml);
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
//        String infoBody = prm.getRdata().getInfoBody("vnd.3gpp.mcdata-info+xml");
//        Log.d(TAG, "onInstantMessage infoBody = " + infoBody);

    }
    @Override
    public void onPublish(OnPublishParam prm) {
        super.onPublish(prm);
        String num = prm.getToUri();
        String mcpttId = imsProfile.getMcpttId();
        Log.d(TAG, "onPublish num = " + num + " mcpttId = " + mcpttId);
        if(num != null
            && num.contains(mcpttId)) {
            String bodyStr = prm.getRdata().getInfoBody(SipManager.SUB_TYPE_EXTENSION);
            Log.d(TAG, "onPublish bodyStr = " + bodyStr);
            if (bodyStr != null
                    && !bodyStr.equals(""))
            {
                Intent intent = new Intent(SipManager.ACTION_SIP_MESSAGE_SYS);
                intent.putExtra(SipManager.Body_Str, bodyStr);
                ctx.sendBroadcast(intent,
                        SipManager.PERMISSION_USE_SIP);
            }
        }
    }


    @Override
    public void onLocationInfo(OnLocationParam prm) {
//        super.onLocationInfo(prm);
        String locationInfoBody = prm.getInfoStr();//.getMsgBody();
        Log.d(TAG, "onLocationInfo locationInfoBody = " + locationInfoBody);
        int index = locationInfoBody.indexOf("<?xml version");
        locationInfoBody = locationInfoBody.substring(index);
        Log.d(TAG, "onLocationInfo locationInfoBody = " + locationInfoBody);
        if (locationInfoBody != null
                && !locationInfoBody.equals("")) {
            Intent intent = new Intent(SipManager.ACTION_SIP_LOCATION);
            intent.putExtra(SipManager.Body_Str, locationInfoBody);
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
    }

    @Override
    public void onMcdataFind(OnMcdataFindParam prm) {
        super.onMcdataFind(prm);
        String infoBody = new String(prm.getInfoStr());
        Log.d(TAG, "onMcdataFind infoBody = " + infoBody);
        if (infoBody != null
                && !infoBody.equals("")) {
            Intent intent = new Intent(SipManager.ACTION_SIP_FD_FIND);
            intent.putExtra(SipManager.Body_Str, infoBody);
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
    }

    @Override
    public void onMcdataMessage(OnMcdataMessageParam prm) {
        super.onMcdataMessage(prm);
        String temp = prm.getInfoStr();
        String mcdataInfoStr = new String(temp);
        Log.d(TAG, "onMcdataMessage mcdataInfoStr = " + mcdataInfoStr);
        temp = prm.getPayloadStr();
        String payloadHexStr = new String(temp);
        Log.d(TAG, "onMcdataMessage payloadHexStr = " + payloadHexStr);
        temp = prm.getSignallingStr();
        String signallingHexStr = new String(temp);
        Log.d(TAG, "onMcdataMessage signallingHexStr = " + signallingHexStr);
        temp = prm.getResourseList();
        String resourceListStr = new String(temp);
        Log.d(TAG, "onMcdataMessage resourceListStr = " + resourceListStr);

        Intent intent = new Intent(SipManager.ACTION_SIP_MCDATA);
        intent.putExtra(SipManager.MSG_INFO_STR, mcdataInfoStr);
        intent.putExtra(SipManager.MSG_PAYLOAD_STR, payloadHexStr);
        intent.putExtra(SipManager.MSG_SIGNALLING_STR, signallingHexStr);
        intent.putExtra(SipManager.MSG_RESOURCE_LIST, resourceListStr);
        ctx.sendBroadcast(intent,
                SipManager.PERMISSION_USE_SIP);
    }

    @Override
    public void onMcdataMessageStatus(OnMcdataMessageStatusParam prm) {
        super.onMcdataMessageStatus(prm);
        String idStr = prm.getIdStr();
        String inXmlBody = prm.getReason();
        Log.d(TAG, "onInstantMessage inXmlBody = " + inXmlBody);
//        if(msgStr != null
//            && msgStr.length() > 0)
//        {
//            int beginIdx = msgStr.indexOf("<IN_XML");
//            int endIdx = msgStr.lastIndexOf("</IN_XML>");
//            inXmlBody = msgStr.substring(beginIdx,endIdx);
//            Log.d(TAG, "onInstantMessage inXmlBody = " + inXmlBody);
//        }
        if (idStr != null
                && !idStr.trim().equals("")) {
            int statusCode = prm.getCode();
            Log.debug(this.getClass(), "onMcdataMessageStatus idStr = " + idStr + " statusCode = " + statusCode);


//            if (statusCode / 100 != 2) {
            Intent intent = new Intent(SipManager.ACTION_SIP_MCDATA_STATUS);
            intent.putExtra(SipManager.Body_IdStr, idStr);
            intent.putExtra(SipManager.Body_StatusCode, statusCode);
            intent.putExtra(SipManager.Body_Str, inXmlBody);
            ctx.sendBroadcast(intent, SipManager.PERMISSION_USE_SIP);
//            }
        }
    }


    @Override
    public void onPublishRsp(OnResponeParam prm) {
        Log.d(TAG, "onPublishRsp prm = " + prm.getResponeCode() + " ResponContent = " + prm.getResponContent() + " type = " + prm.getType());
        if(prm.getType() == CallAttr.McType_McPtt
                || prm.getType() == CallAttr.McType_McVideo
                || prm.getType() == CallAttr.McType_McData)
        {
            Intent intent = new Intent(SipManager.ACTION_SIP_PUBLISH);
            intent.putExtra(SipManager.RESULT_CODE, prm.getResponeCode());
            intent.putExtra(SipManager.RESULT_MCTYPE, prm.getType());
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
        else if(prm.getType() == 5)
        {
            String content = prm.getResponContent();
            Log.d(TAG, "onPublishRsp content = " + content);
            boolean isHave = content.contains("pidf+xml");
            Log.d(TAG, "onPublishRsp isHave = " + isHave);
            if (content != null
                    && content.contains("pidf+xml")) {

                int beginIndex = content.indexOf("<Msg>");
                int endIndex = content.indexOf("</Msg>");
                Log.d(TAG, "onPublishRsp beginIndex = " + beginIndex + " endIndex = " + endIndex);
                String err = content.substring(beginIndex + "<Msg>".length(), endIndex);
                Log.d(TAG, "onPublishRsp err = " + err);

                Intent intent = new Intent(SipManager.ACTION_SIP_PUBLISH_FUNC);
                intent.putExtra(SipManager.RESULT_CODE, prm.getResponeCode());
                intent.putExtra(SipManager.EXT_STR, err);
                ctx.sendBroadcast(intent, SipManager.PERMISSION_USE_SIP);
            }
        }
    }


    @Override
    public void onSubscribeRsp(OnResponeParam prm) {
        Log.d(TAG, "onSubscribeRsp ResponeCode = " + prm.getResponeCode());
        Log.d(TAG, "onSubscribeRsp Type = " + prm.getType());
        Log.d(TAG, "onSubscribeRsp ResponContent = " + prm.getResponContent());
        super.onSubscribeRsp(prm);

        int mcType = prm.getType();
        if(mcType == CallAttr.McType_McPtt
                || mcType == CallAttr.McType_McVideo
                || mcType == CallAttr.McType_McData)
        {
            Intent intent = new Intent(SipManager.ACTION_SIP_SUBSCRIBE);
            intent.putExtra(SipManager.RESULT_CODE, prm.getResponeCode());
            intent.putExtra(SipManager.RESULT_MCTYPE, CallAttr.McType_McPtt);
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
        else
        {
            String content = prm.getResponContent();
            final String BeginKey = "<fail-info>";
            final String EndKey = "</fail-info>";
            int beginIndex = content.indexOf(BeginKey);
            int endIndex = content.indexOf(EndKey);
            Log.d(TAG, "onSubscribeRsp beginIndex = " + beginIndex + " endIndex = " + endIndex);
            if(endIndex > beginIndex) {
                String err = content.substring(beginIndex, endIndex+EndKey.length());
                Log.d(TAG, "onSubscribeRsp err = " + err);
                Intent intent = new Intent(SipManager.ACTION_SIP_SUBSCRIBE_FUNC);
                intent.putExtra(SipManager.RESULT_CODE, prm.getResponeCode());
                intent.putExtra(SipManager.EXT_STR, err);
                ctx.sendBroadcast(intent,
                        SipManager.PERMISSION_USE_SIP);
            }
        }
    }

    @Override
    public void onPresenceInfo(OnMwiInfoParam prm) {
        super.onPresenceInfo(prm);
        String bodyStr = prm.getRdata().getInfoBody(SUB_TYPE_pidf);
        Log.d(TAG, "onPresenceInfo bodyStr = " + bodyStr);
        if (bodyStr != null
                && !bodyStr.equals("")) {
            Intent intent = new Intent(SipManager.ACTION_SIP_NOTIFY);
            intent.putExtra(SipManager.Body_Str, bodyStr);
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
    }

    @Override
    public void onXcapInfo(OnMwiInfoParam prm) {
        super.onXcapInfo(prm);
        String bodyStr = prm.getRdata().getInfoBody(SUB_TYPE_XCAP);
        Log.d(TAG, "onXcapInfo bodyStr = " + bodyStr);
        if (bodyStr != null
                && !bodyStr.equals("")) {
            Intent intent = new Intent(SipManager.ACTION_SIP_NOTIFY_XCAP_DIFF);
            intent.putExtra(SipManager.Body_Str, bodyStr);
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
    }

    @Override
    public void onConferenceInfo(OnMwiInfoParam prm) {
        super.onConferenceInfo(prm);
//        String infoStr = prm.getRdata().getInfoBody(SUB_TYPE_MCPTT_INFO);
        String bodyStr = prm.getRdata().getInfoBody(SipManager.SUB_TYPE_CONFERENCE);
//        Log.d(TAG, "onConferenceInfo infoStr = " + infoStr);
        Log.d(TAG, "onConferenceInfo bodyStr = " + bodyStr);
        if (bodyStr != null
                && !bodyStr.equals("")) {
            Intent intent = new Intent(SipManager.ACTION_SIP_NOTIFY_CONFERENCE);
//            intent.putExtra(SipManager.Info_Str, infoStr);
            intent.putExtra(SipManager.Body_Str, bodyStr);
            ctx.sendBroadcast(intent,
                    SipManager.PERMISSION_USE_SIP);
        }
    }

    public String toString() {
        StringBuffer strBuf = new StringBuffer();
        strBuf.append("MyAccount").append(";");
        strBuf.append("accCfg").append("=").append(accCfg).append(";");
        strBuf.append("Id").append("=").append(this.getId()).append(";");
        strBuf.append("num").append("=").append(num).append(";");
        try {
            strBuf.append("Info").append("=").append(this.getInfo()).append(";");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return strBuf.toString();
    }

    public String getNum() {
        return num;
    }


    public String getNewCallIdStr(int callType, int callDir) {
        Log.d(TAG, "addMyCall callMap = " + callMap);
        MyCall call = new MyCall(ctx, this, -1);
        call.updateCallInfo(CallAttr.DEF_CALL_ID_STR, callType, callDir);
        callMap.put(CallAttr.DEF_CALL_ID_STR, call);
        return CallAttr.DEF_CALL_ID_STR;
    }

    public void addMyCall(String callIdStr, MyCall call) {
        Log.d(TAG, "addMyCall callIdStr = " + callIdStr);
        Log.d(TAG, "addMyCall callMap = " + callMap);
        if (callMap != null
                && callMap.get(callIdStr) != null) {
            callMap.remove(callIdStr);
        }
        if (callMap != null
                && callIdStr != null) {
            callMap.put(callIdStr, call);
        }
    }

    public void delMyCall(String callIdStr) {
        Log.d(TAG, "delMyCall callIdStr = " + callIdStr);
        Log.d(TAG, "delMyCall callMap = " + callMap);
        if (callMap != null
                && callIdStr != null) {
            MyCall call = callMap.get(callIdStr);
            call.clean();
            callMap.remove(callIdStr);
        }
    }

    public MyCall getMyCall(String callIdStr) {
        Log.d(TAG, "getMyCall callIdStr = " + callIdStr);
        Log.d(TAG, "getMyCall callMap = " + callMap);
        if (callMap != null) {
            return callMap.get(callIdStr);
        }
        return null;
    }

    public int checkSystemErr() {
        Log.e(TAG, "checkSystemErr num is " + num);
        if (num == null
                || num.equals("")) {
            return CauseCont.OperateCheck_Sys_AccountNumNull;
        }

        return CauseCont.OperateCheck_Suc;
    }

    public ImsProfile getImsProfile() {
        return imsProfile;
    }
//    private int checkCall()
//    {
//        Log.e(TAG, "checkIsMySelf num is " + num);
////        if(num == null
////                || num.equals(""))
////        {
////            return CauseCont.OperateCheck_Call_NumNull;
////        }
//
//        Log.e(TAG, "checkIsMySelf myNum is " + myNum + " num is " + num);
//        if(num == null
//                || num.equals(""))
//        {
//            return CauseCont.OperateCheck_Call_NumNull;
//        }
//        return CauseCont.OperateCheck_Suc;
//    }
}
